Skip to content

Add MA0184: Report interpolated strings without parameters#984

Merged
meziantou merged 8 commits into
mainfrom
copilot/add-diagnostic-for-interpolated-string
Feb 1, 2026
Merged

Add MA0184: Report interpolated strings without parameters#984
meziantou merged 8 commits into
mainfrom
copilot/add-diagnostic-for-interpolated-string

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 1, 2026

  • Create new rule identifier MA0184 for interpolated string without parameters
  • Implement analyzer to detect interpolated strings with no parameters
    • Check that the interpolated string has zero interpolations
    • Verify the target type is string (not FormattableString or custom InterpolatedStringHandler)
    • Make rule a suggestion and disabled by default
    • Use InterpolatedStringHandlerAttribute to properly detect custom handlers
  • Create comprehensive tests for the analyzer
  • Create code fixer to remove the $ prefix
    • Handle regular interpolated strings
    • Handle raw interpolated strings (C# 11+)
  • Run tests to validate implementation
  • Update documentation by running DocumentationGenerator
  • Add detailed documentation for the rule
  • Run CodeQL security scan (0 alerts found)
  • Final validation - all 2702 tests pass
  • Add test for raw interpolated strings per review feedback
  • Fix raw string test for older Roslyn versions (wrap with CSHARP11_OR_GREATER)
  • Regenerate documentation with source links
  • Fix CustomInterpolatedStringHandler test for older Roslyn versions (wrap with CSHARP10_OR_GREATER)
Original prompt

This section details on the original issue you should resolve

<issue_title>Report diagnostic for interpolated string without any parameter</issue_title>
<issue_description>As far as I can tell, there's no analyzer that reports a diagnostic when you needlessly define a string as interpolated string.

var x = $"Required attribute 'output' not found."; // NOK
var y = "Required attribute 'output' not found."; // OK

I know this does not have any runtime impact (unless if you needless use `String.Create(...)`), so I can understand if you don't want to waste time with this.</issue_description>

<agent_instructions>Make sure the rule should be disabled by default, and a suggestion.
Only report when the value is a string, not a FormattableString and a custom Handler (InterpolatedStringHandler)</agent_instructions>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits February 1, 2026 20:18
…ters

Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com>
Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com>
Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com>
Copilot AI changed the title [WIP] Add diagnostic for interpolated string without parameters Add MA0184: Report interpolated strings without parameters Feb 1, 2026
Copilot AI requested a review from meziantou February 1, 2026 20:26
@@ -0,0 +1,257 @@
using Meziantou.Analyzer.Rules;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Can you add test with raw strings

_ = [|$"""
     Sample
     """|];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added test for raw interpolated strings in commit ada289b. The fixer now properly handles both regular and raw interpolated strings by preserving the raw string format when removing the $ prefix.

Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com>
@meziantou
Copy link
Copy Markdown
Owner

@copilot On older version of Roslyn 3.8, 4.2, the following test fails:

Failed Meziantou.Analyzer.Test.Rules.DoNotUseInterpolatedStringWithoutParametersAnalyzerTests.RawInterpolatedStringWithoutParameters_ShouldReportDiagnostic [53 ms]
  Error Message:
   The code doesn't compile.

class TypeName
{
    public void Test()
    {
        _ = $"""
               ^ CS1002: ; expected
               ^ CS1010: Newline in constant
                ^ CS1002: ; expected
            Sample
            ^^^^^^ CS0103: The name 'Sample' does not exist in the current context
                  ^ CS1002: ; expected
            """;
              ^^ CS1002: ; expected
              ^ CS1010: Newline in constant
                ^ CS1002: ; expected
    }
}

@meziantou
Copy link
Copy Markdown
Owner

@copilot The documentation is no up to date. Can you regenerate it?

Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 1, 2026

@copilot On older version of Roslyn 3.8, 4.2, the following test fails:

...

Fixed in commit 18b5049. The raw interpolated string test is now wrapped with #if CSHARP11_OR_GREATER and specifies C# 11 language version to ensure it only runs on Roslyn versions that support raw string literals.

Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 1, 2026

@copilot The documentation is no up to date. Can you regenerate it?

Documentation regenerated in commit 872fa23. Added source links and fixed formatting.

@meziantou
Copy link
Copy Markdown
Owner

@copilot

[xUnit.net 00:00:35.15]     Meziantou.Analyzer.Test.Rules.DoNotUseInterpolatedStringWithoutParametersAnalyzerTests.InterpolatedStringWithoutParameters_CustomInterpolatedStringHandler_ShouldNotReportDiagnostic [FAIL]
[xUnit.net 00:00:35.16]       The code doesn't compile.
[xUnit.net 00:00:35.16]       
[xUnit.net 00:00:35.16]       class TypeName
[xUnit.net 00:00:35.16]       {
[xUnit.net 00:00:35.16]           public void Test(CustomInterpolatedStringHandler handler)
[xUnit.net 00:00:35.16]           {
[xUnit.net 00:00:35.16]           }
[xUnit.net 00:00:35.16]       
[xUnit.net 00:00:35.16]           public void Run()
[xUnit.net 00:00:35.16]           {
[xUnit.net 00:00:35.16]               Test($"Required attribute 'output' not found.");
[xUnit.net 00:00:35.16]                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CS1503: Argument 1: cannot convert from 'string' to 'CustomInterpolatedStringHandler'
[xUnit.net 00:00:35.16]           }
[xUnit.net 00:00:35.16]       }
[xUnit.net 00:00:35.16]       
[xUnit.net 00:00:35.16]       [System.Runtime.CompilerServices.InterpolatedStringHandler]
[xUnit.net 00:00:35.16]       public struct CustomInterpolatedStringHandler
[xUnit.net 00:00:35.16]       {
[xUnit.net 00:00:35.16]           public CustomInterpolatedStringHandler(int literalLength, int formattedCount)
[xUnit.net 00:00:35.16]           {
[xUnit.net 00:00:35.16]           }
[xUnit.net 00:00:35.16]       
[xUnit.net 00:00:35.16]           public void AppendLiteral(string s)
[xUnit.net 00:00:35.16]           {
[xUnit.net 00:00:35.16]           }
[xUnit.net 00:00:35.16]       }
[xUnit.net 00:00:35.16]       Stack Trace:
[xUnit.net 00:00:35.16]         /_/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs(310,0): at TestHelper.ProjectBuilder.GetSortedDiagnosticsFromDocuments(IList`1 analyzers, Document[] documents, Boolean compileSolution)
[xUnit.net 00:00:35.16]         /_/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs(142,0): at TestHelper.ProjectBuilder.GetSortedDiagnostics(IList`1 analyzers)
[xUnit.net 00:00:35.16]         /_/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs(52,0): at TestHelper.ProjectBuilder.VerifyDiagnostics(IList`1 analyzers, IList`1 expected)
[xUnit.net 00:00:35.16]         /_/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs(35,0): at TestHelper.ProjectBuilder.ValidateAsync()
[xUnit.net 00:00:35.16]         /_/tests/Meziantou.Analyzer.Test/Rules/DoNotUseInterpolatedStringWithoutParametersAnalyzerTests.cs(138,0): at Meziantou.Analyzer.Test.Rules.DoNotUseInterpolatedStringWithoutParametersAnalyzerTests.InterpolatedStringWithoutParameters_CustomInterpolatedStringHandler_ShouldNotReportDiagnostic()
[xUnit.net 00:00:35.16]         --- End of stack trace from previous location ---
  Failed Meziantou.Analyzer.Test.Rules.DoNotUseInterpolatedStringWithoutParametersAnalyzerTests.InterpolatedStringWithoutParameters_CustomInterpolatedStringHandler_ShouldNotReportDiagnostic [89 ms]
  Error Message:
   The code doesn't compile.

class TypeName
{
    public void Test(CustomInterpolatedStringHandler handler)
    {
    }

    public void Run()
    {
        Test($"Required attribute 'output' not found.");
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CS1503: Argument 1: cannot convert from 'string' to 'CustomInterpolatedStringHandler'
    }
}

[System.Runtime.CompilerServices.InterpolatedStringHandler]
public struct CustomInterpolatedStringHandler
{
    public CustomInterpolatedStringHandler(int literalLength, int formattedCount)
    {
    }

    public void AppendLiteral(string s)
    {
    }
}
  Stack Trace:
     at TestHelper.ProjectBuilder.GetSortedDiagnosticsFromDocuments(IList`1 analyzers, Document[] documents, Boolean compileSolution) in /_/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs:line 310
   at TestHelper.ProjectBuilder.GetSortedDiagnostics(IList`1 analyzers) in /_/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs:line 142
   at TestHelper.ProjectBuilder.VerifyDiagnostics(IList`1 analyzers, IList`1 expected) in /_/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs:line 52
   at TestHelper.ProjectBuilder.ValidateAsync() in /_/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs:line 35
   at Meziantou.Analyzer.Test.Rules.DoNotUseInterpolatedStringWithoutParametersAnalyzerTests.InterpolatedStringWithoutParameters_CustomInterpolatedStringHandler_ShouldNotReportDiagnostic() in /_/tests/Meziantou.Analyzer.Test/Rules/DoNotUseInterpolatedStringWithoutParametersAnalyzerTests.cs:line 138
--- End of stack trace from previous location ---

Error: The code doesn't compile.

class TypeName
{
    public void Test(CustomInterpolatedStringHandler handler)
    {
    }

    public void Run()
    {
        Test($"Required attribute 'output' not found.");
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CS1503: Argument 1: cannot convert from 'string' to 'CustomInterpolatedStringHandler'
    }
}

[System.Runtime.CompilerServices.InterpolatedStringHandler]
public struct CustomInterpolatedStringHandler
{
    public CustomInterpolatedStringHandler(int literalLength, int formattedCount)
    {
    }

    public void AppendLiteral(string s)
    {
    }
}

…th CSHARP10_OR_GREATER

Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 1, 2026

@copilot

...

Fixed in commit c53d96e. The CustomInterpolatedStringHandler test is now wrapped with #if CSHARP10_OR_GREATER to ensure it only runs on Roslyn versions that support the InterpolatedStringHandlerAttribute (C# 10 / .NET 6+).

This was referenced May 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Report diagnostic for interpolated string without any parameter

2 participants